/*
handlers 执行函数回调
by:wjc


*/
package tugou

import (
	"errors"
	"reflect"
	"strings"
	"tugou/logs"
	"tugou/utils"
	// "tugou"
)

var (
	Err_Hander_No_Find_Handler     = errors.New("hander no find name handler")
	Err_Hander_No_Find_ClassHander = errors.New("hander no find name ClassHandler")
)

type asyncCall struct { //异步回调
	method  reflect.Value //回调函数
	hasAttr bool          //是否带属性
	args    reflect.Type  //回调类型
}
type syncCall struct { //同步回调
	method  reflect.Value //回调函数
	hasAttr bool          //是否带属性
	args    reflect.Type  //回调类型
	reply   reflect.Type  //返回参数
}

func VerifyHandler(extend interface{}) reflect.Type { //验证modulei
	//验证模块名称

	value := reflect.ValueOf(extend)
	extendType := value.Type()
	name := extendType.Name()
	logs.Info("验证[" + name + "]模块")
	//idType := reflect.TypeOf(string)
	//	plyaerGateType := reflect.TypeOf(Gate{})
	if value.Kind().String() != "ptr" { //验证接口是否为指针接口
		panic("player的方法应该是 func(xx *XX)xxx(){},不满足应该实现指针方法")
	}
	for i := 0; i < value.NumMethod(); i++ { //批量查看方法
		method := extendType.Method(i)
		name := method.Name
		inNum := method.Type.NumIn()
		outNum := method.Type.NumOut()

		if strings.HasPrefix(name, Func_Perfix_By_Client) || strings.HasPrefix(name, Func_Loc_PerFix) { //外网函数和内网
			if outNum == 0 { //异步
				if inNum != 3 {
					panic(name + "模块的" + name + "函数 参数必须为2个")
				}
			} else if outNum == 1 { //同步
				if inNum != 3 {
					panic(name + "模块的" + name + "函数 参数必须为3个")
				}
				if method.Type.Out(0).String() != "error" {
					panic(name + "模块的" + name + "返回参数必须是errors")
				}
				if (method.Type.In(1).Name() != "pId" && method.Type.In(1).Name() != "mName") || method.Type.In(1).String() != "string" {
					panic(name + "模块的" + name + "第一个参数不是 string 或mName pId")
				}
				if method.Type.In(3).String() != "ptr" {
					panic(name + "模块的" + name + "第三个参数必须是指针")
				}
			} else {
				panic(name + "模块的" + name + "非法参数")
			}
		}
	}
	logs.Info("验证[" + name + "]模块通过")
	return extendType.Elem()
}

type handler struct {
	asyncCalls map[string]map[string]*asyncCall //异步回调
	syncCalls  map[string]map[string]*syncCall  // 同步回调
}

func NewHandler(extend interface{}, perfixs ...string) handler { //新建
	h := handler{}
	h.bind(extend, perfixs...)
	return h
}

// func (this *handler) bind(extend interface{}, perfixs ...string) { //绑定函数
// 	if extend == nil {
// 		panic("绑定对象不能为空")
// 		return
// 	}
// 	if this.asyncCalls == nil {
// 		this.asyncCalls = make(map[string]map[string]*asyncCall)

// 	}
// 	if this.syncCalls == nil {
// 		this.syncCalls = make(map[string]map[string]*syncCall)

// 	}
// 	value := reflect.ValueOf(extend)
// 	valueType := value.Type()
// 	logs.Debug("开始绑定")
// 	for i := 0; i < value.NumMethod(); i++ {
// 		method := value.Method(i)
// 		methodType := valueType.Method(i)
// 		name := methodType.Name
// 		inNum := methodType.Type.NumIn()
// 		outNum := methodType.Type.NumOut()

// 		for _, perfix := range perfixs {
// 			if strings.HasPrefix(name, perfix) {
// 				if outNum == 0 { //异步消息
// 					asyncCalls, ok := this.asyncCalls[perfix]
// 					if !ok {
// 						//classHandler =
// 						asyncCalls = make(map[string]*asyncCall)
// 						this.asyncCalls[perfix] = asyncCalls

// 					}
// 					async := &asyncCall{}
// 					if inNum == 2 { //只有一个参数
// 						argsType := methodType.Type.In(1)
// 						argsTypeName := argsType.Name()
// 						if argsType.String() == "string" && (argsTypeName == "pId" || argsTypeName == "mName") {
// 							async.hasAttr = true
// 						} else {
// 							async.hasAttr = false
// 							async.args = argsType
// 						}
// 					} else if inNum == 3 { //有2个参数
// 						argsType := methodType.Type.In(2)
// 						async.hasAttr = true
// 						async.args = argsType
// 					}
// 					asyncCalls[name] = async
// 				} else if outNum == 1 { //同步消息
// 					syncCalls, ok := this.syncCalls[perfix]
// 					if !ok {
// 						//classHandler =
// 						syncCalls = make(map[string]*syncCall)
// 						this.syncCalls[perfix] = syncCalls

// 					}
// 					sync := &syncCall{}
// 					if inNum == 2 { //只有一个参数
// 						argsType := methodType.Type.In(1)
// 						argsTypeString := argsType.String()
// 						argsTypeName := argsType.Name()
// 						if argsTypeString == "string" && (argsTypeName == "pId" || argsTypeName == "mName") {
// 							sync.hasAttr = true
// 						} else if argsTypeString == "ptr" { //如果是指针，这是返回函数
// 							sync.hasAttr = false
// 							sync.reply = argsType
// 						} else {
// 							sync.hasAttr = false
// 							sync.args = argsType
// 						}
// 					} else if inNum == 3 { //有2个参数
// 						argsType1 := methodType.Type.In(1)
// 						argsTypeString1 := argsType1.String()
// 						argsTypeName1 := argsType1.Name()
// 						argsType2 := methodType.Type.In(2)
// 						argsTypeString2 := argsType2.String()
// 						argsTypeName2 := argsType2.Name()
// 						if argsTypeString1 == "string" && (argsTypeName1 == "pId" || argsTypeName1 == "mName") {
// 							sync.hasAttr = true
// 						} else {
// 							sync.hasAttr = false
// 							sync.args = argsType1
// 						}
// 						if argsTypeString2 == "ptr" { //如果是指针，这是返回函数
// 							sync.hasAttr = false
// 							sync.reply = argsType2
// 						} else {
// 							sync.hasAttr = false
// 							sync.args = argsType2
// 						}
// 					} else if inNum == 4 { //有3个参数
// 						argsType2 := methodType.Type.In(2)
// 						agrsType3 := methodType.Type.In(3)
// 						syncCall.hasAttr = true
// 						syncCall.args = argsType2
// 						syncCall.reply = argsType3
// 					}
// 					syncCalls[name] = syncCall
// 				}
// 			}
// 		}
// 	}
// 	logs.Info("绑定完", handler)
// }
func (this *handler) bind(extend interface{}) { //绑定函数
	if extend == nil {
		panic("绑定对象不能为空")
		return
	}
	if this.asyncCalls == nil {
		this.asyncCalls = make(map[string]map[string]*asyncCall)

	}
	if this.syncCalls == nil {
		this.syncCalls = make(map[string]map[string]*syncCall)

	}
	value := reflect.ValueOf(extend)
	valueType := value.Type()
	logs.Debug("开始绑定")
	for i := 0; i < value.NumMethod(); i++ {
		method := value.Method(i)
		methodType := valueType.Method(i)
		name := methodType.Name
		//		inNum := methodType.Type.NumIn()
		outNum := methodType.Type.NumOut()

		for _, perfix := range perfixs {
			if strings.HasPrefix(name, perfix) {
				if outNum == 0 { //异步消息
					asyncCalls, ok := this.asyncCalls[perfix]
					if !ok {
						//classHandler =
						asyncCalls = make(map[string]*asyncCall)
						this.asyncCalls[perfix] = asyncCalls

					}
					async := &asyncCall{}
					argsType := methodType.Type.In(2)
					async.hasAttr = true
					async.args = argsType
					async.method = method
					asyncCalls[name] = async
				} else if outNum == 1 { //同步消息
					syncCalls, ok := this.syncCalls[perfix]
					if !ok {
						//classHandler =
						syncCalls = make(map[string]*syncCall)
						this.syncCalls[perfix] = syncCalls

					}
					sync := &syncCall{}
					argsType2 := methodType.Type.In(2)
					argsType3 := methodType.Type.In(3)
					sync.hasAttr = true
					sync.args = argsType2
					sync.reply = argsType3
					sync.method = method

					syncCalls[name] = sync
				}
			}
		}
	}
	logs.Info("绑定完", this)
}
func (this *handler) callAsync(perfix string, name string, datas ...interface{}) error { //回调网络
	logs.Info(this)
	asyncCalls, ok := this.asyncCalls[perfix]
	if ok {
		asyncCall, ok := asyncCalls[name]
		if ok {
			datasCount := len(datas)
			if datasCount != 2 {
				return errors.New("执行函数" + name + "执行参数与传送参数不一致")
			}
			refdatas := []reflect.Value{reflect.ValueOf(datas[0])}
			data := datas[1]
			dataType := reflect.TypeOf(datas[1])
			dataValue := reflect.ValueOf(data)
			dataTypeString := dataType.Kind().String()
			argsType := asyncCall.args
			aresTypeString := argsType.Kind().String()
			if argsType == dataType { //如果数据相等
				refdatas = append(refdatas, dataValue)
			} else if dataTypeString == "map" {
				callData := reflect.New(argsType.Elem()).Interface()
				err := utils.MapToStruct(data, callData)
				if err != nil {
					return err
				}
				if aresTypeString == "ptr" {
					refdatas = append(refdatas, reflect.ValueOf(callData).Elem())
				} else if aresTypeString == "struct" {
					refdatas = append(refdatas, reflect.ValueOf(callData))
				} else {
					return errors.New("传入参数不正确")
				}
			}
			asyncCall.method.Call(refdatas)
			return nil
		}
		return Err_Hander_No_Find_Handler
	}
	return Err_Hander_No_Find_ClassHander
}

// func (this handler) callAsync(perfix string, name string, datas ...interface{}) error { //回调网络
// 	logs.Info(handler)
// 	classHandler, ok := handler.ClassHandlers[perfix]
// 	if ok {
// 		callFunc, ok := classHandler[name]
// 		if ok {
// 			datasCount := len(datas)
// 			if len(callFunc.Params) == 2 {
// 				return errors.New("执行函数" + name + "执行参数与传送参数不一致")
// 			}
// 			refdatas := []reflect.Value{}
// 			for k, _ := range callFunc.Params {
// 				parmType := callFunc.Params[k]
// 				data := datas[k]
// 				dataType := reflect.TypeOf(data)
// 				dataValue := reflect.ValueOf(data)
// 				dataTypeString := dataType.Kind().String()
// 				parmTypeString := parmType.Kind().String()
// 				if parmType == dataType { //如果数据相等
// 					refdatas = append(refdatas, dataValue)
// 				} else if dataTypeString == "map" {
// 					callData := reflect.New(parmType.Elem()).Interface()
// 					err := utils.MapToStruct(data, callData)
// 					if err != nil {
// 						return err
// 					}
// 					if parmTypeString == "ptr" {
// 						refdatas = append(refdatas, reflect.ValueOf(callData).Elem())
// 					} else if parmTypeString == "struct" {
// 						refdatas = append(refdatas, reflect.ValueOf(callData))
// 					} else {
// 						return errors.New("传入参数不正确")
// 					}
// 				}

// 			}
// 			callFunc.Func.Call(refdatas)
// 			return nil
// 		}
// 		return Err_Hander_No_Find_Handler
// 	}
// 	return Err_Hander_No_Find_ClassHander
// }
